// /////////////////////////////////////////////////////////////////////////////
//
// Name:            EntityManager.cpp
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           The Entity Manager is the central interface point to all
//                  entity related functions of this program.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

// Include files
#include "EntityManager.h"
#include "GameManager.h"

#include "../components/components.h"


// EntityManager class
// EntityManager constructor.
EntityManager::EntityManager()
{
    init();
}

// EntityManager deconstructor.
EntityManager::~EntityManager()
{
    clear();
}

// Initialises the Entity Manager.
void EntityManager::init()
{
}

// Clears the Entity Manager.
void EntityManager::clear()
{
    // Clear entities.
    removeEntities();
}

// Increases the reference counter.
void EntityManager::grab()
{
    // Dummy function.
}

// Decreases the reference counter.
void EntityManager::drop()
{
    // Dummy function.
}

// Adds an entity to the Entity Manager.
bool EntityManager::addEntity(Entity *entity)
{
    // Did we get a valid pointer?
    if(entity == NULL)
      return false;

    // Look if a entity with given name doesn't already exist.
    if(getEntity(entity->getName()))
      return false;

    // Add the entity.
    mEntities.push_back(entity);
    entity->grab();

    return true;
}

// Creates (and adds) an entity with the given name and adds it to the Entity Manager.
Entity* EntityManager::createEntity(const std::string &name, Entity *parent, AssetGroup* assets, bool grab)
{
    // Look if a entity with given name doesn't already exist.
    if(grab && getEntity(name))
      return NULL;

    // Add the entity.
    Entity *entity = new Entity(name, parent, assets);

    if(grab)
    {
       mEntities.push_back(entity);
       entity->grab();
    }

    return entity;
}

// Creates an entity from the given XML file.
Entity* EntityManager::createEntityFromXML(const std::string &fileName, Entity *parent, AssetGroup *assets, bool grab)
{
    // Get pointer to the File System of Irrlicht.
    IFileSystem *fileSystem = GameManager::Instance()->getDevice()->getFileSystem();

    // Does the file exist?
    if(!fileSystem->existFile(fileName.c_str()))
      return NULL;

    // Open the file.
    IXMLReader *file = fileSystem->createXMLReader(fileName.c_str());

    return createEntityFromXML(file, parent, assets, grab);
}

// Creates an Entity from a XML file through a IXMLReader object.
Entity* EntityManager::createEntityFromXML(IXMLReader *file, Entity *parent, AssetGroup *assets, bool grab)
{
    // Create the entity.
    Entity *entity = new Entity("", parent, assets);

    // Deserialize the entity from the given XML file.
    if(entity->loadXML(file))
    {
       if(grab)
       {
          // Check if we don't already have an entity with the same name.
          if(getEntity(entity->getName()) != NULL)
          {
             entity->drop();
             return NULL;
          }

          // Add the entity.
          mEntities.push_back(entity);
          entity->grab();
       }

       return entity;
    }

    // In case deserialization has failed, we will drop the entity and return a NULL pointer.
    entity->drop();
    return NULL;
}

// Gets the entity with the given ID.
Entity* EntityManager::getEntity(const u32 id)
{
    for(u32 i = 0; i < mEntities.size(); i++)
    {
       if(mEntities[i]->getID() == id)
         return mEntities[i];
    }

    return NULL;
}

// Gets the entity with the given name.
Entity* EntityManager::getEntity(const std::string &name)
{
    for(u32 i = 0; i < mEntities.size(); i++)
    {
       if(mEntities[i]->getName() == name)
         return mEntities[i];
    }

    return NULL;
}

// Removes all entities.
void EntityManager::removeEntities()
{
    for(u32 i = 0; i < mEntities.size(); i++)
      mEntities[i]->drop();

    mEntities.clear();
}

// Removes the given entity.
bool EntityManager::removeEntity(Entity *entity)
{
    // Did we get a valid pointer?
    if(entity == NULL)
      return false;

    // Try to remove the entity.
    vector<Entity*>::iterator it;

    for(it = mEntities.begin(); it < mEntities.end(); it++)
    {
        Entity *ent = *it;

        if(ent == entity)
        {
           ent->drop();
           mEntities.erase(it);
           return true;
        }
    }

    // We couldn't find the entity and thus couldn't remove it.
    return false;
}

// Removes the entity with the given ID.
bool EntityManager::removeEntity(const u32 id)
{
    // Try to remove the entity.
    vector<Entity*>::iterator it;

    for(it = mEntities.begin(); it < mEntities.end(); it++)
    {
        Entity *ent = *it;

        if(ent->getID() == id)
        {
           ent->drop();
           mEntities.erase(it);
           return true;
        }
    }

    // We couldn't find the entity and thus couldn't remove it.
    return false;
}

// Removes the entity with the given name.
bool EntityManager::removeEntity(const std::string &name)
{
    // Try to remove the entity.
    vector<Entity*>::iterator it;

    for(it = mEntities.begin(); it < mEntities.end(); it++)
    {
        Entity *ent = *it;

        if(ent->getName() == name)
        {
           ent->drop();
           mEntities.erase(it);
           return true;
        }
    }

    // We couldn't find the entity and thus couldn't remove it.
    return false;
}

// End of File
